/**
 * Created by meiguizhinian on 2018/6/26
 * Copyright © 2018 lixiaolong. All rights reserved.
 */

//TODO：等待完成
//单例/全静态
ivy.UIManager = {
	getInstance: function () {
		return this;
	},
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//初始化UI基础信息
	initUIDataWithFile : function (filepath) {
		let is = new ivy.InputStream(filepath);
		cc.assert(!is.empty(),"读取文件失败"+filepath);
		let aniCount = is.readJInt16();
		this.aniFileNames_ = [];
		for (let i = 0; i < aniCount; ++i) {
			this.aniFileNames_[i] = is.readStringUTF8();
		}

		let formTextDataCount = is.readJInt16();
		for (let i = 0; i < formTextDataCount; ++i)
		{
			let textBlockDataCount = is.readJInt16();
			for (let j = 0; j < textBlockDataCount; ++j) {
				//这是什么？
				let signData = is.readJInt16();
			}
			let textData = is.readStringUTF8();
			this.textDatas_.push(textData);
		}

		let formCount = is.readJInt16();
		this.formCount_ = formCount;
		this.blocksDataVec_ = [];

		for (let i = 0; i < formCount; ++i) {
			let blockTreeDataTempMap = {};
			let formContolCount = is.readJInt16();
			let formName = is.readStringUTF8();
			this.allBlockTreeData_.push(new ivy.BlockTreeData(formName, ""));
			let rootBlockTreeData = this.allBlockTreeData_[this.allBlockTreeData_.length-1];
			this.blocksDataVec_[i] = [];
			for (let j=0; j!==formContolCount; ++j) {
				this.blocksDataVec_[i][j] = [];
			}
			for (let j = 0; j < formContolCount; ++j) {
				let blockName = is.readStringUTF8();
				let fatherBlockName = is.readStringUTF8();
				//0层数据不添加进blockTree中
				if (j > 0) {
					let d = new ivy.BlockTreeData(blockName,fatherBlockName);
					this.allBlockTreeData_.push(d);
					blockTreeDataTempMap[blockName] = d;
				}
				if (blockName.length > 0) {
					if (!this.uiDataIndexFindMap_[formName]) {
						this.uiDataIndexFindMap_[formName] = {};
					}
					this.uiDataIndexFindMap_[formName][blockName] = new ivy.UIDataIndex(i, j,fatherBlockName);
				}
				let dataCount = ivy.UIManager.FormDataType.eEnumCount;
				for (let k = 0; k < dataCount-3; ++k) {
					this.blocksDataVec_[i][j].push(is.readJInt16());
				}
				if (this.blocksDataVec_[i][j][0] === 3) {
					this.blocksDataVec_[i][j].push(is.readJInt16());
					this.blocksDataVec_[i][j].push(is.readJInt16());
					this.blocksDataVec_[i][j].push(is.readJInt16());
				} else {
					this.blocksDataVec_[i][j].push(-1);
					this.blocksDataVec_[i][j].push(-1);
					this.blocksDataVec_[i][j].push(-1);
				}
			}
			//以下代码生成了当前form的节点树信息
			let ownedByRootDataBlockNameVec = [];
			for (let kv in blockTreeDataTempMap) {
				if (!blockTreeDataTempMap.hasOwnProperty(kv)) {
					continue;
				}
				let second = blockTreeDataTempMap[kv];
				if (second.fatherBlockName.length > 0) {
					if (blockTreeDataTempMap[second.fatherBlockName]) {
						blockTreeDataTempMap[second.fatherBlockName].childBlockTreeData[kv] = second;
					}
				} else {
					//此处将位于根节点的block名称暂存 因为不能保证所有的根节点一定在子节点之后处理
					ownedByRootDataBlockNameVec.push(kv);
				}
			}
			for (let kkk=0; kkk!==ownedByRootDataBlockNameVec.length; ++kkk) {
				let name = ownedByRootDataBlockNameVec[kkk];
				if (blockTreeDataTempMap[name]) {
					rootBlockTreeData.childBlockTreeData[name] = blockTreeDataTempMap[name];
				}
			}
			this.formBlockTreeDataMap_[formName] = rootBlockTreeData;
			//以上代码生成了当前form的节点树信息
		}
	},
	//初始化UI自定义控件相关信息
	initUIControlDataWithFile : function(filepath) {
		let is = new ivy.InputStream(filepath);
		cc.assert(!is.empty(), "文件不存在"+filepath);
		let sourceControlCount = is.readJInt16();
		for (let i = 0; i < sourceControlCount; ++i) {
			let typeName=is.readStringUTF8();
			let propertyCount = is.readJInt16();
			let uiSCT = new ivy.UISourceControlType(typeName);
			for (let j = 0; j < propertyCount; ++j) {
				let propertyType = is.readJInt16();
				uiSCT.getElementTypeVec().push(propertyType);
			}
			this.uiSourceControlTypeVec_.push(uiSCT);
		}

		let useControlFormCount = is.readJInt16();
		for (let i = 0; i < useControlFormCount; ++i) {
			let formName = is.readStringUTF8();
			let useControlBlockCount = is.readJInt16();
			for (let j = 0; j < useControlBlockCount; ++j) {
				let blockName = is.readStringUTF8();
				let sourceControlType = is.readJInt16();
				if (sourceControlType >= 0) {
					let uiSCD = new ivy.UISourceControlData();
					uiSCD.sourceControlTypeIndex = sourceControlType;
					let propertyCount = is.readJInt16();
					cc.assert(propertyCount===this.uiSourceControlTypeVec_[sourceControlType].size(), "数量错误");
					let sourceControlPropertyVec = this.uiSourceControlTypeVec_[sourceControlType].getElementTypeVec();
					for (let k = 0; k < propertyCount; ++k) {
						switch (sourceControlPropertyVec.get(k)) {
							case ivy.UISourceControlType.BaseElementType.eInt: {
								let v = is.readJInt32();
								if (this.controlDataIntFindMap_.has(v)) {
									uiSCD.propertyDataFindIndex.push(this.controlDataIntFindMap_.get(v));
								} else {
									let len = this.controlDataIntMap_.size();

									this.controlDataIntFindMap_.set(v, len);
									uiSCD.propertyDataFindIndex.push(this.controlDataIntFindMap_.get(v));
									this.controlDataIntMap_.set(len, v);
								}
								break;
							}
							case ivy.UISourceControlType.BaseElementType.eList:
							case ivy.UISourceControlType.BaseElementType.eAction: {
								let v = is.readJInt16();
								if (this.controlDataIntFindMap_.has(v)) {
									uiSCD.propertyDataFindIndex.push(this.controlDataIntFindMap_.get(v));
								} else {
									let len = this.controlDataIntMap_.size();

									this.controlDataIntFindMap_.set(v, len);
									uiSCD.propertyDataFindIndex.push(this.controlDataIntFindMap_.get(v));
									this.controlDataIntMap_.set(len, v);
								}
								break;
							}
							case ivy.UISourceControlType.BaseElementType.eString: {
								let v = is.readStringUTF8();
								if (this.controlDataStringFindMap_.has(v)) {
									uiSCD.propertyDataFindIndex.push(this.controlDataStringFindMap_.get(v));
								} else {
									let len = this.controlDataStringMap_.size();

									this.controlDataStringFindMap_.set(v, len);
									uiSCD.propertyDataFindIndex.push(this.controlDataStringFindMap_.get(v));
									this.controlDataStringMap_.set(len, v);
								}
								break;
							}
							case ivy.UISourceControlType.BaseElementType.eColor: {
								let v = is.readJUInt32();
								if (this.controlDataUIntFindMap_.has(v)) {
									uiSCD.propertyDataFindIndex.push(this.controlDataUIntFindMap_.get(v));
								} else {
									let len = this.controlDataUIntMap_.size();

									this.controlDataUIntFindMap_.set(v, len);
									uiSCD.propertyDataFindIndex.push(this.controlDataUIntFindMap_.get(v));
									this.controlDataUIntMap_.set(len, v);
								}
								break;
							}
							case ivy.UISourceControlType.BaseElementType.eFloat: {
								let vInt = is.readJInt32();
								let v = vInt / 100.0;
								if (this.controlDataFloatFindMap_.has(v)) {
									uiSCD.propertyDataFindIndex.push(this.controlDataFloatFindMap_.get(v));
								} else {
									let len = this.controlDataFloatMap_.size();

									this.controlDataFloatFindMap_.set(v, len);
									uiSCD.propertyDataFindIndex.push(this.controlDataFloatFindMap_.get(v));
									this.controlDataFloatMap_.set(len, v);
								}
								break;
							}
							default:
								break;
						}
					}
					if (!this.uiSourceControlDataMap_[formName]) {
						this.uiSourceControlDataMap_[formName] = {}
					}
					if (!this.uiSourceControlDataMap_[formName][blockName]) {
						this.uiSourceControlDataMap_[formName][blockName] = {}
					}
					this.uiSourceControlDataMap_[formName][blockName] = uiSCD;
				}
			}
		}
	},
	//通过ID获取UI基础信息/通过名称获取UI基础信息
	/**
	 *
	 *  getBlockDataByType(formID, blockID, type)
	 *  getBlockDataByType(formName, blockName, type)
	 * */
	getBlockDataByType : function(formIDOrName, blockIDOrName, type) {
		let formID, blockID;
		if (typeof(formIDOrName)==="string") {
			let formName = formIDOrName;
			let blockName = blockIDOrName;
			if (this.uiDataIndexFindMap_[formName] && this.uiDataIndexFindMap_[formName][blockName])
			{
				let index = this.uiDataIndexFindMap_[formName][blockName];
				formID = index.formIndex;
				blockID = index.blockIndex;
			}
		} else {
			formID = formIDOrName;
			blockID = blockIDOrName;
		}

		if (formID>=0 && formID<this.blocksDataVec_.length && blockID>=0 && blockID<=this.blocksDataVec_[formID].length) {
			return this.blocksDataVec_[formID][blockID][type];
		}
		return 0;
	},
	// //通过名称获取父节点名称
	// getBlockFatherName : function(formName, blockName){
	//
	// },
	//获取Block的编辑器区域
	getBlockRect : function(formName, blockName) {
		if (this.uiDataIndexFindMap_[formName] && this.uiDataIndexFindMap_[formName][blockName]) {
			let UIDataIndex = this.uiDataIndexFindMap_[formName][blockName];
			let x= this.getBlockDataByType(UIDataIndex.formIndex, UIDataIndex.blockIndex, ivy.UIManager.FormDataType.ePosX);
			let y = this.getBlockDataByType(UIDataIndex.formIndex, UIDataIndex.blockIndex, ivy.UIManager.FormDataType.ePosY);
			let w = this.getBlockDataByType(UIDataIndex.formIndex, UIDataIndex.blockIndex, ivy.UIManager.FormDataType.eWidth);
			let h = this.getBlockDataByType(UIDataIndex.formIndex, UIDataIndex.blockIndex, ivy.UIManager.FormDataType.eHeight);
			return cc.rect(x, y, w, h);
		}
		else
			return cc.rect();
	},
	//////////////////////////////////////////////////////////////////////////
	//通过ui内部的动画id获取对应动画文件名称
	getAniFileNameByUIAniID : function(id) {
		if (id >= 0 && id < this.aniFileNames_.length) {
			return this.aniFileNames_[id];
		}
		cc.log("getAniFileNameByUIAniID 未找到文件名");
		return null;
	},
	//////////////////////////////////////////////////////////////////////////
	// //调用所有存储的刷新函数
	// callUIRefreshFunctions : function() {
	//
	// },
	callUIRefreshFunctionsWithName : function(name) {
		if (this.uiRefreshFunctionWithNameMap_[name]) {
			let callRefMap = this.uiRefreshFunctionWithNameMap_[name];
			for (let itr in callRefMap) {
				if (!callRefMap.hasOwnProperty(itr)) {
					continue;
				}
				callRefMap[itr]();
			}
		}
	},
	// //增加对应控件的刷新函数
	registerUIRefreshFunction : function(base, func) {
		this.uiRefreshFunctionMap_[base] = func;
	},
	registerUIRefreshFunctionWithName : function(callName, base, func) {
		if (!this.uiRefreshFunctionWithNameMap_[callName]) {
			this.uiRefreshFunctionWithNameMap_[callName] = {};
		}
		this.uiRefreshFunctionWithNameMap_[callName][base] = func;
	},
	// //单个特殊控件刷新
	// void callSpecialUIRefreshFunctions(const std::string& formName, const std::string& blockName);
	// void removeSpecialUIRefreshFunction(const std::string& formName, const std::string& blockName);
	// void removeAllSpecialUIRefreshFunction();
	// void registerSpecialUIRefreshFunction(UIBase* base, std::function<void(void)> func);
	// void registerSpecialUIRefreshFunction(const std::string& formName, const std::string& blockName, std::function<void(void)> func);
	// //移除对应控件的刷新函数
	removeUIRefreshFunction : function(base) {
		if (this.uiRefreshFunctionMap_[base]) {
			this.uiRefreshFunctionMap_[base] = null;
		}
	},
	/**
	 * removeUIRefreshByNameFunction(UIBase* base);
	 * removeUIRefreshByNameFunction(const std::string& callname);
	 * */
	removeUIRefreshByNameFunction : function(baseOrCallname) {
		if (typeof(baseOrCallname)==="string") {
			if (this.uiRefreshFunctionWithNameMap_[baseOrCallname]) {
				this.uiRefreshFunctionWithNameMap_[baseOrCallname] = null;
			}
		} else {
			let base = baseOrCallname;
			let delVec = [];
			for (let kv in this.uiRefreshFunctionWithNameMap_) {
				if (!this.uiRefreshFunctionWithNameMap_.hasOwnProperty(kv)) {
					continue;
				}
				let second = this.uiRefreshFunctionWithNameMap_[kv];
				if (second[base]) {
					second[base] = null;
				}
				if (Object.size(second) <= 0) {
					delVec.push(kv);
				}
			}
			for (let delName in delVec) {
				if (!delVec.hasOwnProperty(delName)) {
					continue;
				}
				this.uiRefreshFunctionWithNameMap_[delName] = null;
			}
		}
	},
	//////////////////////////////////////////////////////////////////////////
	createFormByName : function(formName, runEnterAction=true) {
		if (this.formBlockTreeDataMap_[formName] && this.uiSourceControlDataMap_[formName]) {
			let formBase = this.getPreCreateUI(formName, formName);
			if (!formBase) {
				formBase = ivy.UIBase.create();
				formBase.setUIElementName(formName, formName);
				if (this.uiCustomControlCreateFuncMap_[formName] && this.uiCustomControlCreateFuncMap_[formName][formName]) {
					//检测到有程序介入代码需要处理
					let param = new ivy.CustomControlCreateFuncParameters(-1, formName, formName, this.uiSourceControlDataMap_[formName], formBase, this.formBlockTreeDataMap_[formName]);
					this.uiCustomControlCreateFuncMap_[formName][formName](param);
				} else {
					this.createElementByBlockTreeData(this.formBlockTreeDataMap_[formName], formBase, this.uiSourceControlDataMap_[formName]);
				}
			}
			if(runEnterAction) {
				formBase.runEnterAction();
			}
			return formBase;
		} else {
			return null;
		}
	},
	// template<typename T>
	// T createFormByNameTo(const std::string& name, bool runEnterAction = true)
	// {
	// 	auto uibase = createFormByName(name, runEnterAction);
	// 	auto form = dynamic_cast<T>(uibase);
	// 	if (form)
	// 		return form;
	// 	if (uibase != nullptr&&uibase->getChildren().size() >= 1)
	// 	{
	// 		return dynamic_cast<T>(uibase->getChildren().at(0));
	// 	}
	// 	else
	// 	{
	// 		return null;
	// 	}
	// }
	createElementByBlockTreeData : function(data, fatherElement, blockSourceControlDataMap) {
		for (let kv in data.childBlockTreeData) {
			if (!data.childBlockTreeData.hasOwnProperty(kv)) {
				continue;
			}
			let second = data.childBlockTreeData[kv];
			if (blockSourceControlDataMap[kv]) {
				let formName = fatherElement.getFormName();
				let formCreate = this.getPreCreateUI(formName, kv);
				if (formCreate) {
					fatherElement.addElement(formCreate);
				} else {
					let uiSourceControlData = blockSourceControlDataMap[kv];
					let sourceControlType = uiSourceControlData.sourceControlTypeIndex;

					if (this.uiCustomControlCreateFuncMap_[formName] && this.uiCustomControlCreateFuncMap_[formName][kv]) {
						//检测到有程序介入代码需要处理
						let param = new ivy.CustomControlCreateFuncParameters(sourceControlType, formName, kv, blockSourceControlDataMap, fatherElement, second);
						this.uiCustomControlCreateFuncMap_[formName][kv](param);
					} else if (this.uiControlCreateFuncMap_[sourceControlType]) {
						//未检测到将继续程序生成
						let formChild = this.createUIControlBySourceControlType(sourceControlType,formName, kv, uiSourceControlData);
						if (formChild) {
							fatherElement.addElement(formChild);
							this.createElementByBlockTreeData(second, formChild, blockSourceControlDataMap);
						}
					}
				}
			}
		}
		if(fatherElement) {
			fatherElement.onChildCreateComplete();
		}
	},
	// //////////////////////////////////////////////////////////////////////////
	registerUIControlCreateFunc : function(tempArray) {
		let paramArray = (tempArray instanceof Array) ? tempArray : arguments;
		cc.assert(paramArray.length%2===0, "参数数量错误");
		for (let i=0; i!==paramArray.length; i+=2) {
			let type = paramArray[i];
			this.uiControlCreateFuncMap_[type] = paramArray[i+1];
		}
	},
	// //////////////////////////////////////////////////////////////////////////
	getControlIntDataByFindIndex : function(index) {
		return this.controlDataIntMap_.get(index) || 0;
	},
	getControlListDataByFindIndex : function(index) {
		return this.getControlIntDataByFindIndex(index);
	},
	getControlActionDataByFindIndex : function(index) {
		return this.getControlIntDataByFindIndex(index);
	},
	getControlUIntDataByFindIndex : function(index) {
		return this.controlDataUIntMap_.get(index) || 0;
	},
	getControlColorDataByFindIndex : function(index) {
		return this.getControlUIntDataByFindIndex(index);
	},
	getControlFloatDataByFindIndex : function(index) {
		return this.controlDataFloatMap_.get(index) || 0;
	},
	getControlStringDataByFindIndex : function(index) {
		return this.controlDataStringMap_.get(index) || "";
	},
	//////////////////////////////////////////////////////////////////////////
	getRunningForm : function(index=ivy.UIManager.MainFormLayerIndex.eDefaultFormLayerIndex) {
		return this.currentRunningForm_.get(index);
	},
	runWithFormByName : function(formName, index=ivy.UIManager.MainFormLayerIndex.eDefaultFormLayerIndex) {
		if (this.currentExistFormMap_.has(index)) {
			if (this.currentExistFormMap_.get(index).has(formName)) {
				if (this.currentRunningForm_.has(index) && this.currentRunningForm_.get(index)!== this.currentExistFormMap_.get(index).has(formName)) {
					this.currentRunningForm_.get(index).runOutAction();
					this.currentRunningForm_.set(index, this.currentExistFormMap_.get(index).get(formName));
				}
				this.currentRunningForm_.get(index).runEnterAction();
			} else {
				let newForm = this.createFormByName(formName);
				if (newForm) {
					this.currentExistFormMap_.get(index).set(newForm.getFormName(), newForm);
					if (this.currentRunningForm_.has(index)) {
						this.currentRunningForm_.get(index).runOutAction();
						this.currentRunningForm_.set(index, newForm);
					} else {
						this.currentRunningForm_.set(index, newForm);
					}
					cc.assert(this.currentUINode_,"节点为空");
					if (this.currentUINode_) {
						this.currentUINode_.addChild(newForm, index);
					}
				}
			}
		} else {
			let newForm = this.createFormByName(formName);
			if (newForm) {
				if (!this.currentExistFormMap_.has(index)) {
					this.currentExistFormMap_.set(index, new LLDictionary())
				}
				this.currentExistFormMap_.get(index).set(newForm.getFormName(), newForm);
				this.currentRunningForm_.set(index, newForm);
				cc.assert(this.currentUINode_,"节点为空");
				if (this.currentUINode_) {
					this.currentUINode_.addChild(newForm, index);
				}
			}
		}
	},

	getFormByName : function(formName, index=ivy.UIManager.MainFormLayerIndex.eDefaultFormLayerIndex, T=ivy.UIBase) {
		//查找所有层
		if (index === ivy.UIManager.MainFormLayerIndex.eInvaildFormLayerIndex) {
			for (let key of this.currentExistFormMap_.keys()) {
				let result = this.getFormByName(formName, key, T);
				if (result) {
					return result;
				}
			}
		} else {
			if (this.currentExistFormMap_.has(index) && this.currentExistFormMap_.get(index).has(formName)) {
				let formBase = this.currentExistFormMap_.get(index).get(formName);
				if (formBase instanceof T) {
					return formBase;
				} else {
					let formTemp = formBase;
					if (formTemp && formTemp.getChildrenCount() >= 1) {
						let node = formTemp.getChildren()[0];
						if (node instanceof T) {
							return node;
						}
					} else {
						return null;
					}
				}
			}
		}
		return null;
	},

	removeExistFormFromMapByName : function(name, index = ivy.UIManager.MainFormLayerIndex.eDefaultFormLayerIndex) {
		if (index === ivy.UIManager.MainFormLayerIndex.eInvaildFormLayerIndex) {
			//所有层中查找删除
			for (let key of this.currentExistFormMap_.keys()) {
				this.removeExistFormFromMapByName(name, key);
			}
		} else {
			if (this.currentExistFormMap_.get(index).size()>0 && this.currentExistFormMap_.get(index).has(name)) {
				this.currentExistFormMap_.get(index).erase(name);
			}
		}
	},
	registUICustomControlCreateFunc : function(formName, blockName, func) {
		if (!this.uiCustomControlCreateFuncMap_[formName]) {
			this.uiCustomControlCreateFuncMap_[formName] = {}
		}
		this.uiCustomControlCreateFuncMap_[formName][blockName] = func;
	},
	createUIControlBySourceControlType : function(sourceControlType, formName, blockName, controlData) {
		if (this.uiControlCreateFuncMap_[sourceControlType]) {
			return this.uiControlCreateFuncMap_[sourceControlType](formName, blockName, controlData);
		} else {
			cc.log("新控件类型",sourceControlType);
			return ivy.UIBase.create();
		}
	},
	//template<class T = UIBase*>
	createUIControlByName : function(formName, blockName, createAllChild=true, T=ivy.UIBase) {
		let blockData = this._getBlockTreeDataByName(formName, blockName);
		if (!blockData)
			return null;
		if (this.uiSourceControlDataMap_[formName] && this.uiSourceControlDataMap_[formName][blockName]) {
			let blockSourceControlData = this.uiSourceControlDataMap_[formName][blockName];
			let sourceControlType = blockSourceControlData.sourceControlTypeIndex;
			let formChild = this.createUIControlBySourceControlType(sourceControlType, formName, blockName, blockSourceControlData);
			if (formChild instanceof T) {
				if (createAllChild) {
					this.createElementByBlockTreeData(blockData, formChild, this.uiSourceControlDataMap_[formName]);
				}
				return formChild;
			}
		}
		return null;
	},
	getUIDataIndexByName : function(formName, blockName) {
		if (this.uiDataIndexFindMap_[formName] && this.uiDataIndexFindMap_[formName][blockName]) {
			return this.uiDataIndexFindMap_[formName][blockName];
		} else {
			return new ivy.UIDataIndex();
		}
	},
	//////////////////////////////////////////////////////////////////////////
	initUISystem : function(sceneNode) {
		let uiMainNode = new cc.Node();
		sceneNode.addChild(uiMainNode, ivy.UIManager.UINodeLayerValue);

		let uiNode = new cc.NodeGrid();
		uiMainNode.addChild(uiNode, ivy.UIManager.UINodeLayerValue);
		let uiPopUpNode= new cc.Node();
		uiMainNode.addChild(uiPopUpNode, ivy.UIManager.UIPopNodeLayerValue);
		let uiTeachNode = new cc.Node();
		uiMainNode.addChild(uiTeachNode, ivy.UIManager.UITeachNodeLayerValue);
		let uiTopNode = new cc.Node();
		uiMainNode.addChild(uiTopNode, ivy.UIManager.UITopNodeLayerValue);
		this.registUINode(uiNode);
		this.registPopUpUINode(uiPopUpNode);
		this.registTeachUINode(uiTeachNode);
		this.registTopUINode(uiTopNode);
		this.currentExistFormMap_.clear();
		this.popUpFormVec_ = [];
		if (this.popUpBlurEffectTexture_)
		{
			this.popUpEffectNode_ = null;
			this.popUpBlurEffectTexture_.setTag(1000000);
			this.popUpBlurEffectTexture_.release();
			this.popUpBlurEffectTexture_ = null;
		}
		uiNode.schedule(function(dt){
			if (this.singleTouchEventCheckTimer_ > 0)
				--this.singleTouchEventCheckTimer_;
		}.bind(this), 0, cc.REPEAT_FOREVER, 0, "singleTouchEventCheckerUpdate");
	},
	//////////////////////////////////////////////////////////////////////////
	popUpFormByName : function(name, useBlurEffect=false) {
		if (this.currentPopUpUINode_) {
			let uibase = this.createFormByName(name);
			if (!uibase) {
				return uibase;
			}
			//仅在弹出第一个界面时创建虚化背景
			if (useBlurEffect && this.popUpFormVec_.length === 0) {
				ivy.Tools.pushFunctionToCocosThread(function() {
					this.showBlurEffect(true);
				});
			}
			this.currentPopUpUINode_.addChild(uibase);
			this.popUpFormVec_.push(uibase);
			let curFormCount = this.popUpFormVec_.length;
			if (this.maxShowPopUpFormCount_ > 0) {
				for (let i = 0; i < curFormCount; ++i) {
					let v = curFormCount - this.maxShowPopUpFormCount_;
					if ((i < v) && (v > 0)) {
						if (this.popUpFormVec_[i].isVisible()) {
							this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							let action = cc.sequence(cc.fadeOut(1.0), cc.hide());
							action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].runAction(action);
						}
					} else {
						if (!this.popUpFormVec_[i].isVisible()) {
							this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].setVisible(true);
							let action = cc.fadeIn(1.0);
							action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].runAction(action);
						}
					}
				}
			}
			return uibase;
		} else {
			return null;
		}
	},
	// template<typename T>
	// T popUpFormByNameTo(const std::string& name, bool useBlurEffect = false)
	// {
	// 	auto uibase = popUpFormByName(name, useBlurEffect);
	// 	auto form = dynamic_cast<T>(uibase);
	// 	if (form)
	// 		return form;
	// 	if (uibase != nullptr&&uibase->getChildren().size() >= 1)
	// 	{
	// 		return dynamic_cast<T>(uibase->getChildren().at(0));
	// 	}
	// else
	// 	{
	// 		return null;
	// 	}
	// }
	getPopUpFormCount : function() {
		return this.popUpFormVec_.length;
	},
	getPopUpForm : function(nameOrIndex, T=ivy.UIBase) {
		if (typeof(nameOrIndex) === "string") {
			for (let i=this.popUpFormVec_.length; i!==0; -i) {
				let node = this.popUpFormVec_[i-1];
				if (node.getFormName() === nameOrIndex) {
					if (node instanceof T) {
						return node;
					} else {
						if (node.getChildrenCount() >= 1) {
							return node.getChildren()[0];
						}
					}
				}
			}
		} else {
			let index = nameOrIndex;
			if (index >= 0 && index < this.popUpFormVec_.length) {
				let node = this.popUpFormVec_[index];
				if (node instanceof T) {
					return node;
				} else {
					if (node.getChildrenCount() >= 1) {
						return node.getChildren()[0];
					}
				}
			}
		}
		return null;
	},

	// void removeAllPopUpForm : function();
	removePopUpForm : function() {
		let size = this.popUpFormVec_.length;
		if (size > 0) {
			let needRemoveForm = this.popUpFormVec_.slice(size - 1);
			if (this.popUpFormVec_.length === 0) {
				ivy.Tools.pushFunctionToCocosThread(function() {
					this.showBlurEffect(false);
				});
			}
			ivy.Tools.pushFunctionToCocosThread(function() {
				needRemoveForm.removeFromParent();
			});
			let curFormCount = this.popUpFormVec_.length;
			if (this.maxShowPopUpFormCount_ > 0) {
				for (let i = 0; i < curFormCount; ++i) {
					let v = curFormCount - this.maxShowPopUpFormCount_;
					if ((i < v) && (v > 0)) {
						if (this.popUpFormVec_[i].isVisible()) {
							this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							let action = cc.sequence(cc.fadeOut(1.0), cc.hide());
							action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].runAction(action);
						}
					} else {
						if (!this.popUpFormVec_[i].isVisible()) {
							this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].setVisible(true);
							let action = cc.fadeIn(1.0);
							action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
							this.popUpFormVec_[i].runAction(action);
						}
					}
				}
			}
		}
	},
	removePopUpFormByName : function(name) {
		for (let i=this.popUpFormVec_.length; i!==0; -i) {
			let node = this.popUpFormVec_[i-1];
			if (node.getFormName()===name) {
				this.popUpFormVec_.splice(i-1);
				ivy.Tools.pushFunctionToCocosThread(function () {
					node.removeFromParent();
				});
				break;
			}
		}
		let curFormCount = this.popUpFormVec_.length;
		if (this.maxShowPopUpFormCount_ > 0)
		{
			for (let i = 0; i < curFormCount; ++i)
			{
				let v = curFormCount - this.maxShowPopUpFormCount_;
				if ((i < v) && (v > 0)) {
					if (this.popUpFormVec_[i].isVisible())
					{
						this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
						let action = cc.sequence(cc.fadeOut(1.0), cc.hide());
						action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
						this.popUpFormVec_[i].runAction(action);
					}
				} else {
					if (!this.popUpFormVec_[i].isVisible()) {
						this.popUpFormVec_[i].stopActionByTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
						this.popUpFormVec_[i].setVisible(true);
						let action =  cc.fadeIn(1.0);
						action.setTag(ivy.UIBase.CommonActionTAG.eMaxCheckShowPopUpFormAction);
						this.popUpFormVec_[i].runAction(action);
					}
				}
			}
		}
	},
	isPopUpFormExit : function(formName) {
		for (let i=0; i!==this.popUpFormVec_.length; ++i) {
			if (this.popUpFormVec_[i]===formName) {
				return true;
			}
		}
		return false;
	},
	getTopPopUpForm : function() {
		let size = this.popUpFormVec_.length;
		if (size > 0) {
			return this.popUpFormVec_[size - 1];
		}
		return null;
	},
	getUINode : function() {
		return this.currentUINode_;
	},
	getUIPopUpNode : function() {
		return this.currentPopUpUINode_;
	},
	getUITeachNode : function() {
		return this.currentTeachUINode_;
	},
	getUITopNode : function() {
		return this.currentTopUINode_;
	},
	//////////////////////////////////////////////////////////////////////////
	// void clear : function()
	// {
	// 	currentUINode_ = nullptr;
	// 	currentPopUpUINode_ = nullptr;
	// 	currentTeachUINode_ = nullptr;
	// 	currentTopUINode_ = nullptr;
	// 	currentRunningForm_.clear();
	// 	currentExistFormMap_.clear();
	// 	popUpEffectNode_ = nullptr;
	// 	popUpEffectSpriteVec_.clear();
	// 	popUpFormVec_.clear();
	// 	uiSpecialRefreshFunctionMap_.clear();
	// 	uiRefreshFunctionMap_.clear();
	// }
	// //////////////////////////////////////////////////////////////////////////
	registerSkipEnterActionElement : function(formName, blockName) {
		if (!this.skipEnterActionElementsMap_.has(formName)) {
			this.skipEnterActionElementsMap_.set(formName, new LLDictionary());
		}
		this.skipEnterActionElementsMap_.get(formName).set(blockName, 0);
	},
	unRegisterSkipEnterActionElement : function(formName, blockName) {
		if (this.skipEnterActionElementsMap_.has(formName) && this.skipEnterActionElementsMap_.get(formName).has(blockName)) {
			this.skipEnterActionElementsMap_.get(formName).erase(blockName);
		}
	},
	isElementSkipEnterAction : function(formName, blockName) {
		return this.skipEnterActionElementsMap_.has(formName) && this.skipEnterActionElementsMap_.get(formName).has(blockName);
	},
	registerSkipOutActionElement : function(formName, blockName) {
		if (!this.skipOutActionElementsMap_.has(formName)) {
			this.skipOutActionElementsMap_.set(formName, new LLDictionary());
		}
		this.skipOutActionElementsMap_.get(formName).set(blockName, 0);
	},
	unRegisterSkipOutActionElement : function( formName, blockName) {
		if (this.skipOutActionElementsMap_.has(formName) && this.skipOutActionElementsMap_.get(formName).has(blockName)) {
			this.skipOutActionElementsMap_[formName].erase(blockName);
		}
	},
	isElementSkipOutAction : function(formName, blockName) {
		return this.skipOutActionElementsMap_.has(formName) && this.skipOutActionElementsMap_.get(formName).has(blockName);
	},

	isAllowMultiFormExist : function(){
		return this.allowMultiFormExist_;
	},
	setAllowMultiFormExist : function(is) {
		this.allowMultiFormExist_ = is;
	},
	//////////////////////////////////////////////////////////////////////////
	// bool preCreateUI : function(const std::string& formName, const std::string& blockName, UIBase* ui);
	isPreCreateUIExist : function(formName, blockName) {
		return this.preCreateMap_[formName] && this.preCreateMap_[formName][blockName];
	},
	getPreCreateUI : function(formName, blockName) {
		if (this.isPreCreateUIExist(formName, blockName)) {
			return this.preCreateMap_[formName][blockName];
		} else {
			return null;
		}
	},
	// void clearAllPreCreateUI : function();
	showBlurEffect : function(show) {
		if (show) {
			if (!this.popUpBlurEffectTexture_) {
				let config = cc.GlobleConfig.getInstance();
				this.popUpBlurEffectTexture_ = ivy.Tools.screenShot(false);
				this.popUpBlurEffectTexture_.retain();
				let pSptBlur = ivy.SpriteBlur.create(this.popUpBlurEffectTexture_.getSprite(), 4, 4);
				pSptBlur.setRotationSkewX(180.0);
				pSptBlur.setPositionX(pSptBlur.getContentSize().width / 2);
				pSptBlur.setPositionY(pSptBlur.getContentSize().height / 2);

				this.popUpBlurEffectTexture_.begin();
				//遍历节点对象，填充纹理到texure中
				pSptBlur.visit();
				//结束获取
				this.popUpBlurEffectTexture_.end();

				//将模糊化后的图片保存成一张图片
				let spriteBlur = new cc.Sprite(this.popUpBlurEffectTexture_.getSprite().getSpriteFrame());
				spriteBlur.setPosition(config.getScreenHalfWidth(), config.getScreenHalfHeight());

				let size = cc.director.getWinSize();
				spriteBlur.setRotationSkewX(180.0);
				spriteBlur.setPosition(size.width / 2, size.height / 2);
				this.popUpEffectNode_ = new cc.Node();
				this.popUpEffectNode_.setCascadeOpacityEnabled(true);
				ivy.UIManager.getInstance().getUIPopUpNode().addChild(this.popUpEffectNode_, -1);
				this.popUpEffectNode_.addChild(spriteBlur);

				this.popUpEffectNode_.setOpacity(0);
				this.popUpEffectNode_.runAction(cc.fadeIn(0.5));
				let sceneNode = ivy.GameObjectManager.getInstance().getSceneObjectNode();
				if (sceneNode) {
					sceneNode.stopAllActions();
					sceneNode.runAction(cc.sequence(cc.fadeOut(0.5), cc.hide()));
				}
			} else {
				ivy.Tools.screenShot(this.popUpBlurEffectTexture_, false);
				let pSptBlur = ivy.SpriteBlur.create(this.popUpBlurEffectTexture_.getSprite(), 4, 4);
				pSptBlur.setRotationSkewX(180.0);
				pSptBlur.setPositionX(pSptBlur.getContentSize().width / 2);
				pSptBlur.setPositionY(pSptBlur.getContentSize().height / 2);

				this.popUpBlurEffectTexture_.begin();
				//遍历节点对象，填充纹理到texure中
				pSptBlur.visit();
				//结束获取
				this.popUpBlurEffectTexture_.end();

				this.popUpEffectNode_.setVisible(true);
				this.popUpEffectNode_.setOpacity(0);
				this.popUpEffectNode_.runAction(cc.fadeIn(0.5));
				let sceneNode = ivy.GameObjectManager.getInstance().getSceneObjectNode();
				if (sceneNode) {
					sceneNode.stopAllActions();
					sceneNode.runAction(cc.sequence(cc.fadeOut(0.5), cc.hide()));
				}
			}
		} else {
			if (this.popUpEffectNode_&& this.popUpEffectNode_.isVisible()) {
				this.popUpEffectNode_.stopAllActions();
				this.popUpEffectNode_.runAction(cc.sequence(cc.fadeOut(0.5), cc.hide()));
			}
			let sceneNode = ivy.GameObjectManager.getInstance().getSceneObjectNode();
			if (sceneNode && !sceneNode.isVisible()) {
				sceneNode.stopAllActions();
				sceneNode.runAction(cc.sequence(cc.show(), cc.fadeIn(0.3)));
			}
		}
	},
	setMaxShowPopUpFormCount : function(count) {
		this.maxShowPopUpFormCount_ = count;
	},
	getMaxShowPopUpFormCount : function() {
		return this.maxShowPopUpFormCount_;
	},
	setIgnoreScrollCheck : function(ignore) {
		this.ignoreScrollCheck_ = ignore;
		if (ignore) {
			this.callUIRefreshFunctionsWithName(ivy.UIListView.UIListViewPauseScrollEventSTR);
		} else {
			this.callUIRefreshFunctionsWithName(ivy.UIListView.UIListViewResumeScrollEventSTR);
		}
	},
	isIgnoreScrollCheck : function(){
		return this.ignoreScrollCheck_;
	},

	// template<typename T>
	// static T convertToCustomFrom(const UIBase* uibase, const std::string& name)
	// {
	// 	return dynamic_cast<T>(((cocos2d::Node*)uibase)->getChildByName(name));
	// }
	resetSingleTouchEventTimer : function() {
		this.singleTouchEventCheckTimer_ = 0;
	},
	isSingleTouchEventAllow : function() {
		return this.singleTouchEventCheckTimer_ <= 0;
	},
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////private
	registUINode : function(node) {
		this.currentUINode_ = node;
	},
	registPopUpUINode : function(node) {
		this.currentPopUpUINode_ = node;
	},
	registTeachUINode : function(node) {
		this.currentTeachUINode_ = node;
	},
	registTopUINode : function(node) {
		this.currentTopUINode_ = node;
	},
	
	_getBlockTreeDataByName : function(formNameOrfatherData, blockName) {
		if (typeof(formNameOrfatherData)==="string") {
			let data = this.formBlockTreeDataMap_[formNameOrfatherData];
			if (data) {
				return this._getBlockTreeDataByName(data, blockName);
			}
		} else {
			let childBlockTreeDataMap = formNameOrfatherData.childBlockTreeData;
			if (childBlockTreeDataMap[blockName]) {
				return childBlockTreeDataMap[blockName];
			} else {
				for (let child in childBlockTreeDataMap) {
					if (!childBlockTreeDataMap.hasOwnProperty(child)) {
						continue;
					}
					let result=this._getBlockTreeDataByName(childBlockTreeDataMap[child], blockName);
					if (result) {
						return result;
					}
				}
			}
		}
		return null;
	},
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	currentExistFormMap_ : new LLDictionary(),//std::map<int32_t,std::map<std::string, UIBase*>>
	//////////////////////////////////////////////////////////////////////////
	currentRunningForm_ : new LLDictionary(),//std::map<int32_t, UIBase*>
	currentUINode_ : null,
	currentPopUpUINode_ : null,
	currentTopUINode_ : null,
	currentTeachUINode_ : null,
	//////////////////////////////////////////////////////////////////////////
	uiSourceControlTypeVec_ : [],//std::vector<UISourceControlType>
	uiSourceControlDataMap_ : {},//std::map<std::string, std::map<std::string, UISourceControlData>>
	controlDataIntMap_ : new LLDictionary(),
	controlDataUIntMap_ : new LLDictionary(),
	controlDataFloatMap_ : new LLDictionary(),
	controlDataStringMap_ : new LLDictionary(),
	//临时容器 数据加载完后释放
	controlDataIntFindMap_ : new LLDictionary(),
	controlDataUIntFindMap_ : new LLDictionary(),
	controlDataFloatFindMap_ : new LLDictionary(),
	controlDataStringFindMap_ : new LLDictionary(),
	//////////////////////////////////////////////////////////////////////////
	uiRefreshFunctionMap_ : {},
	uiRefreshFunctionWithNameMap_ : {},
	uiSpecialRefreshFunctionMap_ : {},
	aniFileNames_ : [],
	textDatas_ : [],
	formCount_ : 0,
	blocksDataVec_ : [],
	uiDataIndexFindMap_ : {},
	formBlockTreeDataMap_ : {},
	//实际BlockTreeData存储区
	allBlockTreeData_ : [],
	//////////////////////////////////////////////////////////////////////////
	//具体UI对象创建函数库(根据不同游戏进行指定)
	uiControlCreateFuncMap_ : {},
	//特定对象创建函数库(程序介入生成入口)
	uiCustomControlCreateFuncMap_ : {},
	//////////////////////////////////////////////////////////////////////////
	popUpFormVec_ : [],
	//////////////////////////////////////////////////////////////////////////
	popUpEffectSpriteVec_ : [],
	popUpEffectNode_ : null,
	popUpBlurEffectTexture_ : null,
	//////////////////////////////////////////////////////////////////////////
	skipEnterActionElementsMap_ : new LLDictionary(),
	skipOutActionElementsMap_ : new LLDictionary(),
	//////////////////////////////////////////////////////////////////////////
	uiRefreshCalled_ : false,
	//////////////////////////////////////////////////////////////////////////
	allowMultiFormExist_ : false,
	//////////////////////////////////////////////////////////////////////////
	preCreateMap_ : {},
	//////////////////////////////////////////////////////////////////////////
	maxShowPopUpFormCount_ : -1,
	ignoreScrollCheck_ : false,
	singleTouchEventCheckTime : 10,
	singleTouchEventCheckTimer_ : 0,
};

ivy.UIManager.UINodeLayerValue = 100;
ivy.UIManager.UIPopNodeLayerValue = 102;
ivy.UIManager.UITeachNodeLayerValue = 103;
ivy.UIManager.UITopNodeLayerValue = 101;

ivy.UIManager.MainFormLayerIndex = {
	eInvaildFormLayerIndex 	: -1,
	eDefaultFormLayerIndex	: 0,
	eCustomFormLayerIndex 	: 1,
	//...其他自定义如有需求外部定义使用
	eTopFormLayerIndex 		: 100,
};

ivy.UIManager.FormDataType = {
	eType				: 0,
	eLayerID			: 1,
	eBgAniID			: 2,
	eBgActionID			: 3,
	eBgSeqID			: 4,
	eComeToSceneType	: 5,
	eScale				: 6,
	eNotVisble			: 7,
	eTextID				: 8,
	ePosX				: 9,
	ePosY				: 10,
	eWidth				: 11,
	eHeight				: 12,
	eAnchor				: 13,
	eScrollType			: 14,
	eCompressX			: 15,
	eCompressY			: 16,
	eStandBy1			: 17,
	eStandBy2			: 18,
	eSelBgAniID			: 19,
	eSelBgActionID		: 20,
	eSelBgSeqID			: 21,
	eComeAniID			: 22,
	eComActionID		: 23,
	eComeSeqID			: 24,
	eEnumCount			: 25,
};
